﻿using System;
using ch.froorider.NGoogleCalendar.tools;
using Google.GData.Calendar;
using Google.GData.Client;
using log4net;

namespace ch.froorider.NGoogleCalendar.googleService
{
    /// <summary>
    /// Wraps all the service // account information into a class.
    /// Stores also the account name etc.
    /// To be sure, that this class is not easy to access from outside the library, it is
    /// declared as internal.
    /// </summary>
    internal class GoogleAccount
    {
		private const string DEFAULT_FEED_URI = "http://www.google.com/calendar/feeds/default";
		private static ILog logger = LogManager.GetLogger(typeof(GoogleAccount));
        private readonly String accountName;
        private readonly String pass;
		private CalendarService service;

        /// <summary>
        /// Constructor. 
        /// </summary>
        /// <param name="accountName">The name of the google account (usually a gmail address)</param>
        /// <param name="pass">The secred word used with the account.</param>
        /// <exception cref="ch.froorider.NGoogleCalendar.tools.NGoogleCalendarException">Exception is thrown when the application couldn't verify the account.</exception>
        public GoogleAccount(String accountName, String pass)
        {
            this.accountName = accountName;
            this.pass = pass;
			service = new CalendarService("NGoogleCalendar");
			if (this.verifyAccount())
			{
				//Do nothing; Everything is alright.
			}
			else
			{
				throw new NGoogleCalendarException("Couldn't access google account. Please check your account information.");
			}
        }

        /// <summary>
        /// Getter property. Gives you access to the calendar service of this account.
        /// </summary>
        public CalendarService Service
        {
            get { return this.service; }
        }

		/// <summary>
		/// Getter proprty. Gives you access on the account name (e.g. sharp.calendar@gmail.com)
		/// </summary>
		public string AccountName
		{
			get { return this.accountName; }
		}

        /// <summary>
        /// Method to test if the given account information is valid.
        /// </summary>
        /// <returns>true if the feed could be accessed. False otherwise</returns>
        /// <exception cref="ch.froorider.NGoogleCalendar.tools.NGoogleCalendarException">is thrown if the credetials were wrong.</exception>
        private Boolean verifyAccount()
        {
			if (service != null)
			{
				logger.Info("Verifying user settings");
				service.setUserCredentials(this.accountName, this.pass);
				AtomFeed feed = null;

				try
				{
					feed = service.Query(new Google.GData.Client.FeedQuery(DEFAULT_FEED_URI));
				}
				catch (InvalidCredentialsException ice)
				{
					logger.Info("Exception caught: " + ice.Message);
					throw new NGoogleCalendarException("Credentials not valid. Check your password.");
				}
				catch (AuthenticationException ae)
				{
					logger.Info("Exception caught: " + ae.Message);
					throw new NGoogleCalendarException("Service name not valid. Check your username / email address.");
				}

				if (feed != null || feed.Authors.Count != 0)
				{
					foreach (AtomPerson person in feed.Authors)
					{
						logger.Info("Author of this feed: " + person.Name);
					}
					return true;
				}
				else
				{
					return false;
				}
			}
			else
			{
				return false;
			}
        }
    }
}
